package top.kpromise.common.utils;

import top.kpromise.common.error.KException;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ValidationUtils {

    private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    /**
     * 验证某个实体类表单
     *
     * @param object 需要验证的表单
     * @return ValidationResult
     */
    public static <T> ValidationResult validateEntity(T object) {
        ValidationResult result = new ValidationResult();
        Set<ConstraintViolation<T>> set = validator.validate(object, Default.class);
        if (set != null && set.size() != 0) {
            result.setHasErrors(true);
            Map<String, String> errorMsg = new HashMap<>();
            for (ConstraintViolation<T> cv : set) {
                errorMsg.put(cv.getPropertyPath().toString(), cv.getMessage());
            }
            result.setAllErrors(errorMsg);
        }
        return result;
    }

    /**
     * 验证一个List里各个子项的数据合法性
     *
     * @param list 需要验证的 list
     * @return ValidationResult
     */
    public static <T> ValidationResult validateList(List<T> list) {
        if (list == null || list.isEmpty()) return null;
        ValidationResult result = new ValidationResult();
        for (T object : list) {
            ValidationResult tmpResult = validateEntity(object);
            if (tmpResult.isHasErrors()) {
                result.setHasErrors(true);
                if (result.getAllErrors() == null) {
                    result.setAllErrors(tmpResult.getAllErrors());
                } else {
                    result.getAllErrors().putAll(tmpResult.getAllErrors());
                }
            }
        }
        return result;
    }

    public static <T> void throwIfValidateFailed(T object) throws Exception {
        throwIfValidateFailed(object, false);
    }

    /**
     * 验证表单，如果失败则抛出异常
     *
     * @param object 需要验证的表单
     */
    public static <T> void throwIfValidateFailed(T object, boolean containsField) throws Exception {
        ValidationResult validationResult = ValidationUtils.validateEntity(object);
        if (validationResult.isHasErrors()) {
            StringBuilder stringBuilder = new StringBuilder();
            for (Map.Entry<String, String> errorInfo : validationResult.getAllErrors().entrySet()) {
                if (containsField) {
                    stringBuilder.append(errorInfo.getKey());
                }
                stringBuilder.append(errorInfo.getValue()).append(";");
            }
            throw new KException(stringBuilder.toString());
        }
    }

    public static <T> void throwIfValidateFailed(List<T> list) throws Exception {
        throwIfValidateFailed(list, false);
    }

    /**
     * 验证表单List，如果失败则抛出异常
     *
     * @param list 需要验证的表单
     */
    public static <T> void throwIfValidateFailed(List<T> list, boolean containsField) throws Exception {
        if (list == null || list.isEmpty()) return;
        for (T object : list) {
            throwIfValidateFailed(object, containsField);
        }
    }
}
